const { ccclass, property } = cc._decorator;
import s from "./ListItem"

enum Vertical {
    Vertical = 1,
    Horizontal = 2
}

enum ScrollType {
    NORMAL = 1,
    ADHERING = 2,
    PAGE = 3
}

@ccclass
export default class List extends cc.Component {
    @property({
        type: cc.Enum({ Vertical: 1, Horizontal: 2 }),
        displayName: '方向',
        visible: true,
    })
    private _direct = 1;

    @property({
        type: cc.Integer,
        displayName: '水平重复次数',
        tooltip: '0为不限定',
        visible: true,
    })
    private _repeatX = 1;

    @property({
        type: cc.Integer,
        displayName: '竖直重复次数',
        tooltip: '0为不限定',
        visible: true,
    })
    private _repeatY = 0;

    @property({
        type: cc.Float,
        displayName: '水平间距',
        visible: true,
    })
    private _spaceX = 0;

    @property({
        type: cc.Float,
        displayName: '竖直间距',
        visible: true,
    })
    private _spaceY = 0;

    @property({
        type: cc.Prefab,
        displayName: 'Item',
        visible: true,
    })
    private _itemPrefab: cc.Prefab = null;

    private _preLen = 0;
    private _array = null;
    private _scrollBar = null;
    private _isVertical = true;
    private _inited = false;
    private _scrollView = null;
    private _content = null;
    private _cellChanged = false;
    private _startIndex = 0;
    private _selectedIndex = -1;
    private _cells = [];
    private _repeatX2 = 1;
    private _repeatY2 = 1;
    private _width = 0;
    private _height = 0;

    public onLoad() {
        this._init();
    };
    public onEnable() {
        this._registerEvent();
    };
    public onDisable() {
        this._unregisterEvent();
    };
    public _registerEvent() {
        this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchStart, this, true);
        this.node.on("touch-up", this._onTouchUp, this);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancelled, this, true);
        this.node.on("scroll-began", this._onScrollBegan, this, true);
        this.node.on("scroll-ended", this._onScrollEnded, this, true);
        this.node.on("scrolling", this._onScrolling, this, true);
        this.node.on(cc.Node.EventType.SIZE_CHANGED, this._onSizeChanged, this);
    };
    public _unregisterEvent() {
        this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchStart, this, true);
        this.node.off("touch-up", this._onTouchUp, this);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancelled, this, true);
        this.node.off("scroll-began", this._onScrollBegan, this, true);
        this.node.off("scroll-ended", this._onScrollEnded, this, true);
        this.node.off("scrolling", this._onScrolling, this, true);
        this.node.off(cc.Node.EventType.SIZE_CHANGED, this._onSizeChanged, this);
    };
    public _onScrollBegan() { };
    public _onScrollEnded() {
        this._onScrolling();
    };
    public _onScrolling(e?) {
        void 0 === e && (e = null);
        this.onScrollBarChange();
    };
    public _onTouchStart() { };
    public _onTouchUp() { };
    public _onTouchCancelled() { };
    public _onSizeChanged() { };
    public checkInited(e) {
        void 0 === e && (e = true);
        if (!this._inited) {
            e && cc.error("List initialization not completed!");
            return false;
        }
        return true;
    };
    public _init() {
        if (!this._inited) {
            this._isVertical = this._direct == n.Vertical;
            this._scrollView = this.node.getComponent(cc.ScrollView);
            this._content = this._scrollView.content;
            if (this._content) {
                this._width = this.node.width;
                this._height = this.node.height;
                this._content.anchorX = 0;
                this._content.anchorY = 1;
                this._content.x = -this._content.parent.width * this._content.parent.anchorX;
                this._content.y = (1 - this._content.parent.anchorY) * this._content.parent.height;
                this._inited = true;
            } else cc.error(this.node.name + "'s cc.ScrollView unset content!");
        }
    };

    get array(): any[] {
        return this._array;
    }

    private _arrayChanged;
    set array(e: any[]) {
        this.scheduleOnce(this.changeCells);
        this._array = e || [];
        this._preLen = this._array.length;
        const t = this._array.length;
        this._selectedIndex = this._selectedIndex < t ? this._selectedIndex : t - 1;
        this.startIndex = this._startIndex;
        this._arrayChanged = true;
    }

    get width(): number {
        return this.node.width;
    }

    set width(e: number) {
        if (this.node.width != e) {
            this.node.width = e;
            this._setCellChanged();
        }
    }

    get height(): number {
        return this.node.height;
    }

    set height(e: number) {
        if (this.node.height != e) {
            this.node.height = e;
            this._setCellChanged();
        }
    }

    get length(): number {
        return this._array ? this._array.length : 0;
    }

    get repeatX(): number {
        return this._repeatX > 0 ? this._repeatX : this._repeatX2 > 0 ? this._repeatX2 : 1;
    }

    set repeatX(e: number) {
        this._repeatX = e;
        this._setCellChanged();
    }

    get repeatY(): number {
        return this._repeatY > 0 ? this._repeatY : this._repeatY2 > 0 ? this._repeatY2 : 1;
    }

    set repeatY(e: number) {
        this._repeatY = e;
        this._setCellChanged();
    }

    get spaceX(): number {
        return this._spaceX;
    }

    set spaceX(e: number) {
        this._spaceX = e;
        this._setCellChanged();
    }

    get spaceY(): number {
        return this._spaceY;
    }

    set spaceY(e: number) {
        this._spaceY = e;
        this._setCellChanged();
    }

    public refresh() {
        this.array = this._array;
    };
    public updateItem(e, t) {
        e.getComponent(s).setData(this._array[t], t);
    };

    private _cellSize;
    private _cellOffset;
    public changeCells() {
        this._cellChanged = false;
        if (this._itemPrefab) {
            var e = this._getOneCell(), t = e.width + this._spaceX || 1, a = e.height + this._spaceY || 1;
            this._width > 0 && (this._repeatX2 = this._isVertical ? Math.round(this._width / t) : Math.ceil(this._width / t));
            this._height > 0 && (this._repeatY2 = this._isVertical ? Math.ceil(this._height / a) : Math.round(this._height / a));
            var o = this._width ? this._width : t * this.repeatX - this._spaceX, i = this._height ? this._height : a * this.repeatY - this._spaceY;
            this._cellSize = this._isVertical ? a : t;
            this._cellOffset = this._isVertical ? a * Math.max(this._repeatY2, this._repeatY) - i - this._spaceY : t * Math.max(this._repeatX2, this._repeatX) - o - this._spaceX;
            var r = this._isVertical ? this.repeatX : this.repeatY, n = (this._isVertical ? this.repeatY : this.repeatX) + 1;
            this._createItems(0, r, 2 * n);
            if (this._array) {
                if (this._arrayChanged) {
                    var l = this._array.length;
                    console.log("this._array", this._array.length);
                    var s = this._isVertical ? o : Math.ceil(l / this.repeatY) * t - this._spaceX, c = this._isVertical ? Math.ceil(l / this.repeatX) * a - this._spaceY : i;
                    this.setContentSize(s, c);
                }
                this.scheduleOnce(this._renderItems);
            }
        }
    };
    public _getOneCell() {
        if (0 === this._cells.length) {
            var e = this.createItem();
            this._cells.push(e);
        }
        return this._cells[0];
    };
    public _createItems(e, t, a) {
        for (var o = this._content, i = this._getOneCell(), r = i.width + this._spaceX, n = i.height + this._spaceY, l = [], s = this._cells.length - 1; s > -1; s--) {
            var c = this._cells[s];
            c.removeFromParent(false);
            l.push(c);
        }
        this._cells.length = 0;
        for (var u = e; u < a; u++) for (var p = 0; p < t; p++) {
            (i = l && l.length ? l.pop() : this.createItem()).x = (this._isVertical ? p : u) * r + i.anchorX * i.width - o.anchorX * o.width;
            i.y = -(this._isVertical ? u : p) * n - i.anchorY * i.height + (1 - o.anchorY) * o.height;
            i.name = "item" + (u * t + p);
            o.addChild(i);
            this.addCell(i);
        }
    };
    public createItem() {
        return cc.instantiate(this._itemPrefab);
    };
    public addCell(e) {
        e.on("click", this.onCellMouse, this);
        this._cells.push(e);
    };
    public onCellMouse(e) {
        var t = e.target, a = this._startIndex + this._cells.indexOf(t);
        a < 0 || (this.selectedIndex = a);
    };
    public changeCellState(e, t) {
        e.getComponent(s).setSelected(t);
    };
    public setContentSize(e, t) {
        this._content.width = e;
        this._content.height = t;
    };
    public getScrollValue() {
        if (this._isVertical) {
            var e = (1 - this._content.parent.anchorY) * this._content.parent.height;
            return this._content.y - e;
        }
        return -this._content.parent.anchorX * this._content.parent.width - this._content.x;
    };
    private _isMoving;
    public onScrollBarChange(e?) {
        void 0 === e && (e = null);
        this.scheduleOnce(this._renderItems);
        var t, a, o = this.getScrollValue(), i = this._isVertical ? this.repeatX : this.repeatY, r = this._isVertical ? this.repeatY : this.repeatX, n = Math.floor(o / this._cellSize) * i, l = 0;
        if (n > this._startIndex) {
            l = n - this._startIndex;
            t = true;
            a = this._startIndex + i * (r + 1);
            this._isMoving = true;
        } else if (n < this._startIndex) {
            l = this._startIndex - n;
            t = false;
            a = this._startIndex - 1;
            this._isMoving = true;
        }
        for (var s = 0; s < l; s++) {
            if (t) {
                var c = this._cells.shift();
                this._cells[this._cells.length] = c;
                var u = a + s;
            } else {
                c = this._cells.pop();
                this._cells.unshift(c);
                u = a - s;
            }
            var p = Math.floor(u / i) * this._cellSize;
            this._isVertical ? c.y = p : c.x = p;
            this.renderItem(c, u);
        }
        this._startIndex = n;
        this.changeSelectStatus();
    };
    public posCell(e, t) {
        var a = this._isVertical ? this.repeatX : this.repeatY, o = (this._isVertical ? this.repeatY : this.repeatX,
            Math.floor(t / a) * this._cellSize);
        this._isVertical ? e.y = -e.anchorY * e.height - o : e.x = e.anchorX * e.width + o;
    };

    public _renderItems(e?, t?, a?) {
        void 0 === t && (t = 0);
        void 0 === a && (a = 0);
        this.renderItems(t, a);
    };
    public renderItems(e?, t?) {
        void 0 === e && (e = 0);
        void 0 === t && (t = 0);
        for (var a = e, o = t || this._cells.length; a < o; a++) this.renderItem(this._cells[a], this._startIndex + a);
        this.changeSelectStatus();
    };
    public renderItem(e, t) {
        if (this._array && t >= 0 && t < this._array.length) {
            e.active = true;
            this.posCell(e, t);
            this.updateItem(e, t);
            this.changeCellState(e, t == this._selectedIndex);
        } else e.active = false;
    };
    public getItem(e) {
        return e > -1 && e < this._array.length ? this._array[e] : null;
    };
    public changeItem(e, t) {
        if (e > -1 && e < this._array.length) {
            this._array[e] = t;
            e >= this._startIndex && e < this._startIndex + this._cells.length && this.renderItem(this.getCell(e), e);
        }
    };
    public setItem(e, t) {
        this.changeItem(e, t);
    };
    public addItem(e) {
        this._array.push(e);
        this.array = this._array;
    };
    public addItemAt(e, t) {
        this._array.splice(t, 0, e);
        this.array = this._array;
    };
    public deleteItem(e) {
        this._array.splice(e, 1);
        this.array = this._array;
    };
    public getCell(e) {
        return e > -1 && this._cells ? this._cells[(e - this._startIndex) % this._cells.length] : null;
    };
    public _setCellChanged() {
        if (!this._cellChanged) {
            this._cellChanged = true;
            this.scheduleOnce(this.changeCells);
        }
    };
    public commitMeasure() {
        this.scheduleOnce(this.changeCells);
    };

    get selectedIndex() {
        return this._selectedIndex;
    }
    set selectedIndex(value) {
        if (this._selectedIndex != value) {
            this._selectedIndex = value;
            this.changeSelectStatus();
            this.startIndex = this._startIndex;
        }
    }

    changeSelectStatus() {
        for (let i = 0, len = this._cells.length; i < len; i++) {
            this.changeCellState(this._cells[i], this._selectedIndex === this._startIndex + i);
        }
    }

    get selectedItem() {
        return this._selectedIndex !== -1 ? this._array[this._selectedIndex] : null;
    }

    set selectedItem(value) {
        this.selectedIndex = this._array.indexOf(value);
    }

    get selection() {
        return this.getCell(this._selectedIndex);
    }

    set selection(value) {
        this.selectedIndex = this._startIndex + this._cells.indexOf(value);
    }

    get startIndex() {
        return this._startIndex;
    }

    set startIndex(value) {
        this._startIndex = value > 0 ? value : 0;
        this.scheduleOnce(() => {
            this._renderItems();
        });
    }
}